home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / kms20src.lha / KMSS / server.c < prev    next >
C/C++ Source or Header  |  1995-09-24  |  57KB  |  2,092 lines

  1. /**********************************
  2.  *              KMS               *
  3.  **********************************/
  4.  
  5. /*************************************************************************
  6.  *
  7.  *   Copyright (C) 1995 Thomas Schwarz
  8.  *                      <kmshq@ruatha.muc.de>
  9.  *                      <Schwarz.Thomas@fhm.de>
  10.  *
  11.  *   This program is free software; you can redistribute it and/or modify
  12.  *   it under the terms of the GNU General Public License as published by
  13.  *   the Free Software Foundation; either version 2 of the License, or
  14.  *   any later version.
  15.  *
  16.  *   This program is distributed in the hope that it will be useful,
  17.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *   GNU General Public License for more details.
  20.  *
  21.  *   You should have received a copy of the GNU General Public License
  22.  *   along with this program; if not, write to the Free Software
  23.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  *
  25.  *************************************************************************/
  26.  
  27. #include <KMS/KMS.h>
  28. #include <KMS/KMS_devlib.h>
  29. #include "KMSServer_rev.h"
  30.  
  31. /* A handy macro to access AbsExecBase. */
  32.  
  33. #define SysBase (*(struct ExecBase **)4L)
  34.  
  35. Prototype UWORD Break(VOID);
  36. Prototype VOID main(UWORD, STRPTR *);
  37. Prototype UBYTE OpenLib(VOID);
  38. Prototype BOOL GetData(VOID);
  39. Prototype VOID GetCharTable(UBYTE);
  40. Prototype BOOL ReadUserList(VOID);
  41. Prototype BOOL WriteUserList(VOID);
  42. Prototype BOOL ReadAreaList(VOID);
  43. Prototype BOOL WriteAreaList(VOID);
  44. Prototype BOOL ReadAccessList(VOID);
  45. Prototype BOOL WriteAccessList(VOID);
  46. Prototype VOID SaveData(VOID);
  47. Prototype VOID ReadSysDat(VOID);
  48. Prototype VOID WriteSysDat(VOID);
  49. Prototype BOOL WaitUntilAlone(VOID);
  50. Prototype VOID Sense(UBYTE);
  51. Prototype VOID Out(STRPTR);
  52. Prototype STRPTR GetSysMsgLine(STRPTR, STRPTR, UWORD);
  53. Prototype BOOL InitAreaFile(VOID);
  54. Prototype BOOL InitUAF(VOID);
  55. Prototype struct KMSBase *GetKMSBase(VOID);
  56.  
  57. /*****************************
  58.  * Externe Globale Variablen *
  59.  *****************************/
  60.  
  61. extern struct IntuitionBase *IntuitionBase;
  62. extern struct GfxBase *GfxBase;
  63.  
  64. extern struct rexxCommandList RCL[];
  65. extern STRPTR KMSTitle;
  66.  
  67. /*********************
  68.  * Globale Variablen *
  69.  *********************/
  70.  
  71. /* Diverse */
  72.  
  73. struct KMSBase *KMSBase = NULL;
  74. UMSAccount SysUMSAccount = 0;
  75. UBYTE ShutDown = 0;
  76.  
  77. /* Rexx-Port-Signalbit */
  78.  
  79. ULONG RexxSignal = 0;
  80.  
  81. /* Name unseres Rexx-Port */
  82.  
  83. STRPTR RexxPortName = "KMS";
  84. STRPTR RexxExtension = "KMS";
  85.  
  86. STRPTR ServerPort = "KMSServer";
  87.  
  88. BPTR StdOut = NULL;
  89.  
  90. /******************************************
  91.  * Break-Handler                          *
  92.  ******************************************
  93.  * I: ---                                 *
  94.  * O: 0                                   *
  95.  ******************************************/
  96.  
  97. /// "Break"
  98.  
  99. UWORD Break(VOID)
  100.    {
  101.    return 0;
  102.    }
  103.  
  104. ///
  105.  
  106. /******************************************
  107.  * Hauptprogramm                          *
  108.  ******************************************
  109.  * I: ---                                 *
  110.  * O: ---                                 *
  111.  ******************************************/
  112.  
  113. /// "main"
  114.  
  115. VOID main(UWORD argc, STRPTR *argv)
  116.    {
  117.    onbreak(Break);
  118.  
  119.    Forbid();
  120.    if (FindPort(ServerPort))
  121.       {
  122.       Permit();
  123.       exit(20);
  124.       }
  125.    else
  126.       CreatePort(ServerPort, 0);
  127.    Permit();
  128.  
  129.    StdOut = (BPTR)Open("CON:0/10//100/KMSServer Error/CLOSE/AUTO/WAIT", MODE_OLDFILE);
  130.  
  131.    if (OpenLib())
  132.       Sense(20);
  133.  
  134.    if (!GetKMSBase())
  135.       Sense(20);
  136.  
  137.    /* Rexx-Port einrichten */
  138.  
  139.    if (!(RexxSignal = upRexxPort(RexxPortName, RCL, RexxExtension, &KMSRexxDisp)))
  140.       {
  141.       Out("FATAL ERROR: couldn't upRexxPort(\"KMS\")");
  142.       Sense(20);
  143.       }
  144.  
  145.    printf(VERS" -*- ©1994 Thomas Schwarz\n");
  146.  
  147.    while(!ShutDown)
  148.       {
  149.       ULONG signal = Wait(RexxSignal | SIGBREAKF_CTRL_C);
  150.       if (signal & SIGBREAKF_CTRL_C)
  151.          {
  152.          SendPortCmd("SHUTDOWN");
  153.          ShutDown = SHUTDOWN_IMMEDIATE;
  154.          }
  155.       else
  156.          dispRexxPort();
  157.       }
  158.  
  159.    WaitUntilAlone();
  160.  
  161.    Sense(0);
  162.    }
  163.  
  164. ///
  165.  
  166. /*******************************************
  167.  * Öffnen der Libraries                    *
  168.  *******************************************
  169.  * I: ---                                  *
  170.  * O: Fehlercode                           *
  171.  *******************************************/
  172.  
  173. /// "OpenLib"
  174.  
  175. UBYTE OpenLib(VOID)
  176.    {
  177.    if (SysBase->LibNode.lib_Version < 37)
  178.       {
  179.       Out("FATAL ERROR: AmigaOS >=2.04 needed");
  180.       return 1;
  181.       }
  182.    
  183.    return 0;
  184.    }
  185.  
  186. ///
  187.  
  188. /***************************************
  189.  * Text-Data aus KMS_SYSTEM.TXT lesen  *
  190.  ***************************************
  191.  * I: ---                              *
  192.  * O: Erfolg Ja/Nein                   *
  193.  ***************************************/
  194.  
  195. /// "GetData"
  196.  
  197. BOOL GetData(VOID)
  198.    {
  199.    TEXT buff[LEN_MSGHEAD+LEN_MOREPRMT+3+1];
  200.    UBYTE n;
  201.    TEXT dos[LEN_DOSPATH+1];
  202.    LONG sysmsgsize;
  203.    BPTR mylock;
  204.    struct FileInfoBlock *fileinfo = (struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR);
  205.    if (!fileinfo)
  206.       {
  207.       Out("FATAL ERROR: out of memory");
  208.       return FALSE;
  209.       }
  210.  
  211.    /* System-Msg-Datei oeffnen */
  212.  
  213.    strcpy(dos, KMSBase->TxtDir);
  214.    strcat(dos, "KMS_SYSTEM.TXT");
  215.  
  216.    if (mylock = Lock(dos, ACCESS_READ))
  217.       {
  218.       if(Examine(mylock, fileinfo))
  219.          {
  220.          sysmsgsize = fileinfo->fib_Size;
  221.          if (!sysmsgsize)
  222.             {
  223.             Out("FATAL ERROR: couldn't get size of KMS_SYSTEM.TXT");
  224.             UnLock(mylock);
  225.             FreeVec(fileinfo);
  226.             return FALSE;
  227.             }
  228.          }
  229.  
  230.       UnLock(mylock);
  231.       }
  232.    else
  233.       {
  234.       Out("FATAL ERROR: couldn't lock KMS_SYSTEM.TXT");
  235.       FreeVec(fileinfo);
  236.       return FALSE;
  237.       }
  238.  
  239.    FreeVec(fileinfo);
  240.  
  241.    KMSBase->SysMsgs = AllocVec(sysmsgsize + 1, MEMF_PUBLIC);
  242.    if (!KMSBase->SysMsgs)
  243.       {
  244.       Out("FATAL ERROR: out of memory");
  245.       return FALSE;
  246.       }
  247.  
  248.    mylock = Open(dos, MODE_OLDFILE);
  249.    if (!mylock)
  250.       {
  251.       Out("FATAL ERROR: couldn't open KMS_SYSTEM.TXT");
  252.       return FALSE;
  253.       }
  254.  
  255.    if (Read(mylock, KMSBase->SysMsgs, sysmsgsize) != sysmsgsize)
  256.       {
  257.       Out("FATAL ERROR: couldn't read KMS_SYSTEM.TXT");
  258.       Close(mylock);
  259.       return FALSE;
  260.       }
  261.  
  262.    Close(mylock);
  263.  
  264.    KMSBase->SysMsgs[sysmsgsize] = '\0';
  265.  
  266.    /* System-Msg-Offset Tabelle fuellen */
  267.  
  268.    UWORD sysmsg = 0;
  269.    TEXT c;
  270.    STRPTR sysmsgdat = KMSBase->SysMsgs;
  271.    c = *(sysmsgdat++);
  272.  
  273.    while(c > 0 && sysmsg < MAXSYSMSG) /* !EOF */
  274.       {
  275.       /* Nächste Label-Marke suchen */
  276.  
  277.       while(c != '@' && c > 0)
  278.          c = *(sysmsgdat++);
  279.  
  280.       if (c == '@')
  281.          {
  282.          /* Labelmarke gefunden -> Offset eintragen */
  283.  
  284.          while(c != '\n' && c > 0)
  285.             c = *(sysmsgdat++);
  286.  
  287.          KMSBase->SysMsgOffsets[sysmsg++] = (UWORD)(sysmsgdat - KMSBase->SysMsgs);
  288.          }
  289.       }
  290.  
  291.    if (sysmsg != MAXSYSMSG)
  292.       {
  293.       Out("FATAL ERROR: Corrupted KMS_SYSTEM.TXT");
  294.       return FALSE;
  295.       }
  296.  
  297.    /* Jetzt diverse Texte einlesen */
  298.  
  299.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[AREAFLAGS_DATA - 1];
  300.    if (!GetSysMsgLine(sysmsgdat, KMSBase->AFlags, strlen(KMSBase->AFlags)))
  301.       Out("WARNING: AREAFLAGS_DATA not found");
  302.  
  303.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[YESNO_DATA - 1];
  304.    if (!GetSysMsgLine(sysmsgdat, KMSBase->YNText, strlen(KMSBase->YNText)))
  305.       Out("WARNING: YESNO_DATA not found");
  306.  
  307.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[MSGLIST_DATA - 1];
  308.    if (!GetSysMsgLine(sysmsgdat, buff, LEN_MSGLIST))
  309.       {
  310.       Out("FATAL ERROR: MSGLIST_DATA not found");
  311.       return FALSE;
  312.       }
  313.    else
  314.       KMSBase->MsgListLine = strdup(buff);
  315.    if (!KMSBase->MsgListLine)
  316.       {
  317.       Out("FATAL ERROR: out of memory");
  318.       return FALSE;
  319.       }
  320.    
  321.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[FILELIST_DATA - 1];
  322.    if (!GetSysMsgLine(sysmsgdat, buff, LEN_FILELIST))
  323.       {
  324.       Out("FATAL ERROR: FILELIST_DATA not found");
  325.       return FALSE;
  326.       }
  327.    else
  328.       KMSBase->FileListLine = strdup(buff);
  329.    if (!KMSBase->FileListLine)
  330.       {
  331.       Out("FATAL ERROR: out of memory");
  332.       return FALSE;
  333.       }
  334.  
  335.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[AREAPATH_DATA - 1];
  336.    if (!GetSysMsgLine(sysmsgdat, buff, LEN_AREALIST1))
  337.       {
  338.       Out("FATAL ERROR: AREAPATH_DATA not found");
  339.       return FALSE;
  340.       }
  341.    else
  342.       KMSBase->AreaListPath = strdup(buff);
  343.    if (!KMSBase->AreaListPath)
  344.       {
  345.       Out("FATAL ERROR: out of memory");
  346.       return FALSE;
  347.       }
  348.  
  349.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[AREAINFO_DATA - 1];
  350.    if (!GetSysMsgLine(sysmsgdat, buff, LEN_AREALIST2))
  351.       {
  352.       Out("FATAL ERROR: AREAINFO_DATA not found");
  353.       return FALSE;
  354.       }
  355.    else
  356.       KMSBase->AreaListInfo = strdup(buff);
  357.    if (!KMSBase->AreaListInfo)
  358.       {
  359.       Out("FATAL ERROR: out of memory");
  360.       return FALSE;
  361.       }
  362.  
  363.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[MSGHEAD_DATA - 1];
  364.    if (!(sysmsgdat = GetSysMsgLine(sysmsgdat, buff, LEN_MSGHEAD)))
  365.       {
  366.       Out("FATAL ERROR: MSGHEAD_DATA not found");
  367.       return FALSE;
  368.       }
  369.    else
  370.       KMSBase->MsgHead[0] = strdup(buff);
  371.    if (!KMSBase->MsgHead[0])
  372.       {
  373.       Out("FATAL ERROR: out of memory");
  374.       return FALSE;
  375.       }
  376.    for(n = 1; n < 4; n++)
  377.       {
  378.       if (!(sysmsgdat = GetSysMsgLine(sysmsgdat, buff, LEN_MSGHEAD)))
  379.          {
  380.          Out("FATAL ERROR: MSGHEAD_DATA not complete");
  381.          return FALSE;
  382.          }
  383.       else
  384.          KMSBase->MsgHead[n] = strdup(buff);
  385.       if (!KMSBase->MsgHead[n])
  386.          {
  387.          Out("FATAL ERROR: out of memory");
  388.          return FALSE;
  389.          }
  390.       }
  391.  
  392.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[MSGINFO_DATA - 1];
  393.    if (!(sysmsgdat = GetSysMsgLine(sysmsgdat, buff, LEN_MSGINFO)))
  394.       {
  395.       Out("FATAL ERROR: MSGINFO_DATA not found");
  396.       return FALSE;
  397.       }
  398.    else
  399.       {
  400.       strcat(buff, " ");
  401.       KMSBase->MsgInfos[0] = strdup(buff);
  402.       }
  403.    if (!KMSBase->MsgInfos[0])
  404.       {
  405.       Out("FATAL ERROR: out of memory");
  406.       return FALSE;
  407.       }
  408.    for(n = 1; n < 15; n++)
  409.       {
  410.       if (!(sysmsgdat = GetSysMsgLine(sysmsgdat, buff, LEN_MSGINFO)))
  411.          {
  412.          Out("FATAL ERROR: MSGINFO_DATA not complete");
  413.          return FALSE;
  414.          }
  415.       else
  416.          {
  417.          strcat(buff, " ");
  418.          KMSBase->MsgInfos[n] = strdup(buff);
  419.          }
  420.       if (!KMSBase->MsgInfos[n])
  421.          {
  422.          Out("FATAL ERROR: out of memory");
  423.          return FALSE;
  424.          }
  425.       }
  426.  
  427.    sysmsgdat = KMSBase->SysMsgs + KMSBase->SysMsgOffsets[MORE_DATA - 1];
  428.    if (!GetSysMsgLine(sysmsgdat, buff, LEN_MOREPRMT+3))
  429.       Out("WARNING: MORE_DATA not found");
  430.    else if (strlen(buff) > 3)
  431.       {
  432.       strncpy(KMSBase->MoreText, buff, 3);
  433.       KMSBase->MoreText[3] = '\0';
  434.       strcpy(KMSBase->MorePrompt, buff+3);
  435.       }
  436.  
  437.    KMSBase->Yes[0] = KMSBase->YNText[YES];
  438.    KMSBase->Yes[1] = '\0';
  439.    KMSBase->No[0] = KMSBase->YNText[NO];
  440.    KMSBase->No[1] = '\0';
  441.  
  442.    return TRUE;
  443.    }
  444.  
  445. ///
  446.  
  447. /***************************************
  448.  * Zeichen-Konvertiertabellen einlesen *
  449.  ***************************************
  450.  * I: Zeichensatz-Nummer               *
  451.  * O: ---                              *
  452.  ***************************************/
  453.  
  454. /// "GetCharTable"
  455.  
  456. VOID GetCharTable(UBYTE charset)
  457.    {
  458.    FILE *file;
  459.    TEXT dos[LEN_DOSPATH+1];
  460.    TEXT line[82];
  461.    UWORD c, cin, cout;
  462.  
  463.    /* Default-Belegung */
  464.  
  465.    for(c = 0; c < 256; c++)
  466.       KMSBase->CharIn[charset][c] = KMSBase->CharOut[charset][c] = c;
  467.  
  468.    /* Tabelle einlesen */
  469.  
  470.    sprintf(dos, "%sKMS_CHAR_%d.DAT", KMSBase->DatDir, charset);
  471.  
  472.    if (file = fopen(dos, "r"))
  473.       {
  474.       c = 0;
  475.  
  476.       while(fgets(line, 82, file))
  477.          {
  478.          if (line[0] != '\0' && line[0] != '#' && line[0] != ';')
  479.             {
  480.             cin = cout = 0;
  481.  
  482.             if (sscanf(line, " %hd %hd", &cin, &cout) == 2)
  483.                {
  484.                KMSBase->CharIn[charset][c] = cin;
  485.                KMSBase->CharOut[charset][c] = cout;
  486.                }
  487.  
  488.             if (c < 255)
  489.                c++;
  490.             }
  491.          }
  492.  
  493.       fclose(file);
  494.       }
  495.    }
  496.  
  497. ///
  498.  
  499. /*********************************
  500.  * Userdatei lesen               *
  501.  * (Nur bei Programmstart)       *
  502.  *********************************
  503.  * I: ---                        *
  504.  * O: Erfolg TRUE/FALSE          *
  505.  *********************************/
  506.  
  507. /// "ReadUserList"
  508.  
  509. BOOL ReadUserList(VOID)
  510.    {
  511.    struct UserNode *upoint;
  512.    struct Userdaten user;
  513.    TEXT buffer[LEN_DOSPATH+1];
  514.    TEXT buff[LEN_REALNAME+2];
  515.    FILE *file;
  516.  
  517.    /* Wenn schon eingelesen, fertig */
  518.  
  519.    upoint = (struct UserNode *)KMSBase->UserList.mlh_Head;
  520.    if (upoint->Node.mln_Succ)
  521.       return TRUE;
  522.  
  523.    /* Einlesen */
  524.  
  525.    ObtainSemaphore(&KMSBase->UserSem);
  526.  
  527.    strcpy(buffer, KMSBase->DatDir);
  528.    strcat(buffer, "KMS_UAF.DAT");
  529.  
  530.    if (!(file = fopen(buffer, "r")))
  531.       {
  532.       ReleaseSemaphore(&KMSBase->UserSem);
  533.       return FALSE;
  534.       }
  535.  
  536.    while(fgets(buff, LEN_NUMBER+2, file))
  537.       {
  538.       if (!(upoint = (struct UserNode *)AllocMem((ULONG)sizeof(struct UserNode), MEMF_PUBLIC|MEMF_CLEAR)))
  539.          {
  540.          Out("FATAL ERROR: couldn't AllocMem(UserNode)");
  541.  
  542.          fclose(file);
  543.  
  544.          ReleaseSemaphore(&KMSBase->UserSem);
  545.  
  546.          return FALSE;
  547.          }
  548.  
  549.       clrmem(&user, sizeof(struct Userdaten));
  550.  
  551.       user.ID = (UWORD)atoi(buff);
  552.       if (fgets(buff, LEN_USERNAME+2, file))
  553.          {
  554.          if (strlen(buff))
  555.             buff[strlen(buff)-1] = '\0'; // Linefeed am Ende entfernen
  556.          strcpy(user.Name, buff);
  557.          }
  558.       if (fgets(buff, LEN_REALNAME+2, file))
  559.          {
  560.          if (strlen(buff))
  561.             buff[strlen(buff)-1] = '\0'; // Linefeed am Ende entfernen
  562.          strcpy(user.RealName, buff);
  563.          }
  564.       if (fgets(buff, LEN_STREET+2, file))
  565.          {
  566.          if (strlen(buff))
  567.             buff[strlen(buff)-1] = '\0'; // Linefeed am Ende entfernen
  568.          strcpy(user.Street, buff);
  569.          }
  570.       if (fgets(buff, LEN_CITY+2, file))
  571.          {
  572.          if (strlen(buff))
  573.             buff[strlen(buff)-1] = '\0'; // Linefeed am Ende entfernen
  574.          strcpy(user.City, buff);
  575.          }
  576.       if (fgets(buff, LEN_PHONE+2, file))
  577.          {
  578.          if (strlen(buff))
  579.             buff[strlen(buff)-1] = '\0';
  580.          strcpy(user.Phone, buff);
  581.          }
  582.       if (fgets(buff, LEN_UPROMPT+2, file))
  583.          {
  584.          if (strlen(buff))
  585.             buff[strlen(buff)-1] = '\0';
  586.          strcpy(user.Prompt, buff);
  587.          }
  588.       if (fgets(buff, LEN_NUMBER+2, file))
  589.          user.Level = (UWORD)atoi(buff);
  590.       if (fgets(buff, LEN_NUMBER+2, file))
  591.          user.Calls = (UWORD)atoi(buff);
  592.       if (fgets(buff, LEN_NUMBER+2, file))
  593.          user.LastCall = (ULONG)atol(buff);
  594.       if (fgets(buff, LEN_NUMBER+2, file))
  595.          user.CharSet = (UBYTE)atoi(buff);
  596.       if (fgets(buff, LEN_NUMBER+2, file))
  597.          user.PageLen = (UBYTE)atoi(buff);
  598.       if (fgets(buff, LEN_NUMBER+2, file))
  599.          user.LineLen = (UBYTE)atoi(buff);
  600.       if (fgets(buff, LEN_NUMBER+2, file))
  601.          user.Protocol = (UBYTE)atoi(buff);
  602.       if (fgets(buff, LEN_NUMBER+2, file))
  603.          user.Flags = (ULONG)atol(buff);
  604.       if (fgets(buff, LEN_NUMBER+2, file))
  605.          user.AccessBits = (ULONG)atol(buff);
  606.       if (fgets(buff, LEN_NUMBER+2, file))
  607.          user.Quota = (UWORD)atoi(buff);
  608.       if (fgets(buff, 15+2, file))
  609.          {
  610.          if (strlen(buff))
  611.             buff[strlen(buff)-1] = '\0';
  612.          }
  613.  
  614.       upoint->UserData = user;
  615.  
  616.       AddTail((struct List *)&KMSBase->UserList, (struct Node *)upoint);
  617.       }
  618.  
  619.    fclose(file);
  620.  
  621.    ReleaseSemaphore(&KMSBase->UserSem);
  622.    return TRUE;
  623.    }
  624.  
  625. ///
  626.  
  627. /*********************************
  628.  * Userdatei schreiben           *
  629.  *********************************
  630.  * I: ---                        *
  631.  * O: Erfolg TRUE/FALSE          *
  632.  *********************************/
  633.  
  634. /// "WriteUserList"
  635.  
  636. BOOL WriteUserList(VOID)
  637.    {
  638.    struct UserNode *upoint;
  639.    TEXT buffer[LEN_DOSPATH+1];
  640.    FILE *file;
  641.    UWORD num = 0;
  642.  
  643.    ObtainSemaphore(&KMSBase->UserSem);
  644.  
  645.    strcpy(buffer, KMSBase->DatDir);
  646.    strcat(buffer, "KMS_UAF.DAT");
  647.  
  648.    if (!(file = fopen(buffer, "w")))
  649.       {
  650.       Out("FATAL ERROR: couldn't write KMS_UAF.DAT");
  651.  
  652.       ReleaseSemaphore(&KMSBase->UserSem);
  653.       return FALSE;
  654.       }
  655.  
  656.    upoint = (struct UserNode *)KMSBase->UserList.mlh_Head;
  657.    while(upoint->Node.mln_Succ)
  658.       {
  659.       upoint->UserData.ID = ++num;
  660.  
  661.       fprintf(file, "%d\n%s\n%s\n%s\n", upoint->UserData.ID,
  662.                                         upoint->UserData.Name,
  663.                                         upoint->UserData.RealName,
  664.                                         upoint->UserData.Street);
  665.       fprintf(file, "%s\n%s\n%s\n",     upoint->UserData.City,
  666.                                         upoint->UserData.Phone,
  667.                                         upoint->UserData.Prompt);
  668.       fprintf(file, "%d\n%d\n%ld\n",    upoint->UserData.Level,
  669.                                         upoint->UserData.Calls,
  670.                                         upoint->UserData.LastCall);
  671.       fprintf(file, "%d\n%d\n%d\n%d\n", upoint->UserData.CharSet,
  672.                                         upoint->UserData.PageLen,
  673.                                         upoint->UserData.LineLen,
  674.                                         upoint->UserData.Protocol);
  675.       fprintf(file, "%ld\n%ld\n%d\n\n", upoint->UserData.Flags,
  676.                                         upoint->UserData.AccessBits,
  677.                                         upoint->UserData.Quota);
  678.  
  679.       upoint = upoint->Node.mln_Succ;
  680.       }
  681.  
  682.    fclose(file);
  683.  
  684.    ReleaseSemaphore(&KMSBase->UserSem);
  685.    return TRUE;
  686.    }
  687.  
  688. ///
  689.  
  690. /*********************************
  691.  * Areadatei lesen               *
  692.  * (Nur bei Programmstart)       *
  693.  *********************************
  694.  * I: ---                        *
  695.  * O: Erfolg TRUE/FALSE          *
  696.  *********************************/
  697.  
  698. /// "ReadAreaList"
  699.  
  700. BOOL ReadAreaList(VOID)
  701.    {
  702.    struct AreaNode *apoint;
  703.    struct Area area;
  704.    TEXT buffer[LEN_DOSPATH+1];
  705.    TEXT buff[LEN_MBNAME+2]; /* MBNAME ist laengstes Element */
  706.    FILE *file;
  707.  
  708.    /* Wenn schon eingelesen, fertig */
  709.  
  710.    apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
  711.    if (apoint->Node.mln_Succ)
  712.       return TRUE;
  713.  
  714.    /* Einlesen */
  715.  
  716.    ObtainSemaphore(&KMSBase->AreaSem);
  717.  
  718.    strcpy(buffer, KMSBase->DatDir);
  719.    strcat(buffer, "KMS_AREAS.DAT");
  720.  
  721.    if (!(file = fopen(buffer, "r")))
  722.       {
  723.       ReleaseSemaphore(&KMSBase->AreaSem);
  724.       return FALSE;
  725.       }
  726.    else
  727.       {
  728.       while(fgets(buff, LEN_AREANAME+2, file))
  729.          {
  730.          if (strlen(buff))
  731.             buff[strlen(buff)-1] = '\0'; /* Linefeed am Ende entfernen */
  732.  
  733.          if (!(apoint = (struct AreaNode *)AllocMem((ULONG)sizeof(struct AreaNode),MEMF_PUBLIC|MEMF_CLEAR)))
  734.             {
  735.             Out("FATAL ERROR: couldn't AllocMem(AreaNode)");
  736.  
  737.             fclose(file);
  738.  
  739.             ReleaseSemaphore(&KMSBase->AreaSem);
  740.             return FALSE;
  741.             }
  742.  
  743.          clrmem(&area, sizeof(struct Area));
  744.  
  745.          strcpy(area.Name, buff);
  746.          if (fgets(buff, LEN_AREAINFO+2, file))
  747.             {
  748.             if (strlen(buff))
  749.                buff[strlen(buff)-1] = '\0'; /* Linefeed am Ende entfernen */
  750.             strcpy(area.Info, buff);
  751.             }
  752.          if (fgets(buff, LEN_MBNAME+2, file))
  753.             {
  754.             if (strlen(buff))
  755.                buff[strlen(buff)-1] = '\0';
  756.             strcpy(area.MBName, buff);
  757.             }
  758.          if (fgets(buff, LEN_FILEAREA+2, file))
  759.             {
  760.             if (strlen(buff))
  761.                buff[strlen(buff)-1] = '\0';
  762.             strcpy(area.FilePath, buff);
  763.             }
  764.          if (fgets(buff, LEN_NUMBER+2, file))
  765.             area.ID = (UWORD)atoi(buff);
  766.          if (fgets(buff, LEN_NUMBER+2, file))
  767.             area.Type = (UBYTE)atoi(buff);
  768.          if (fgets(buff, LEN_NUMBER+2, file))
  769.             area.ReadLevel = (UBYTE)atoi(buff);
  770.          if (fgets(buff, LEN_NUMBER+2, file))
  771.             area.WriteLevel = (UBYTE)atoi(buff);
  772.          if (fgets(buff, LEN_NUMBER+2, file))
  773.             area.EditLevel = (UBYTE)atoi(buff);
  774.          if (fgets(buff, LEN_NUMBER+2, file))
  775.             area.AccessBits = (ULONG)atol(buff);
  776.          if (fgets(buff, LEN_NUMBER+2, file))
  777.             area.WriteFlag = (UWORD)atol(buff);
  778.          if (fgets(buff, LEN_NUMBER+2, file))
  779.             area.QuoteStr = (UBYTE)atoi(buff);
  780.          if (fgets(buff, LEN_NUMBER+2, file))
  781.             area.PQuoteStr = (UBYTE)atoi(buff);
  782.          if (fgets(buff, LEN_NUMBER+2, file))
  783.             area.ResendStr = (UBYTE)atoi(buff);
  784.          if (fgets(buff, LEN_NUMBER+2, file))
  785.             area.ForwardStr = (UBYTE)atoi(buff);
  786.          if (fgets(buff, LEN_NUMBER+2, file))
  787.             area.OriginStr = (UBYTE)atoi(buff);
  788.          if (fgets(buff, LEN_NUMBER+2, file))
  789.             area.HoldNum = (UWORD)atoi(buff);
  790.          if (fgets(buff, LEN_NUMBER+2, file))
  791.             area.HoldDays = (UWORD)atoi(buff);
  792.          if (fgets(buff, LEN_NUMBER+2, file))
  793.             area.Mother = (UWORD)atoi(buff);
  794.          if (fgets(buff, LEN_NUMBER+2, file))
  795.             area.Daughter = (UWORD)atoi(buff);
  796.          if (fgets(buff, LEN_NUMBER+2, file))
  797.             area.Next = (UWORD)atoi(buff);
  798.  
  799.          apoint->AreaData = area;
  800.  
  801.          AddTail((struct List *)&KMSBase->AreaList,(struct Node *)apoint);
  802.          }
  803.       fclose(file);
  804.       }
  805.  
  806.    ReleaseSemaphore(&KMSBase->AreaSem);
  807.    return TRUE;
  808.    }
  809.  
  810. ///
  811.  
  812. /*********************************
  813.  * Areadatei schreiben           *
  814.  *********************************
  815.  * I: ---                        *
  816.  * O: Erfolg TRUE/FALSE          *
  817.  *********************************/
  818.  
  819. /// "WriteAreaList"
  820.  
  821. BOOL WriteAreaList(VOID)
  822.    {
  823.    struct AreaNode *apoint;
  824.    TEXT buff[LEN_DOSPATH+1];
  825.    FILE *file;
  826.  
  827.    ObtainSemaphore(&KMSBase->AreaSem);
  828.  
  829.    strcpy(buff, KMSBase->DatDir);
  830.    strcat(buff, "KMS_AREAS.DAT");
  831.  
  832.    file = fopen(buff, "w");
  833.    if (!file)
  834.       {
  835.       Out("FATAL ERROR: couldn't write KMS_AREAS.DAT");
  836.  
  837.       ReleaseSemaphore(&KMSBase->AreaSem);
  838.       return FALSE;
  839.       }
  840.  
  841.    apoint = (struct AreaNode *)KMSBase->AreaList.mlh_Head;
  842.    while(apoint->Node.mln_Succ)
  843.       {
  844.       fprintf(file,"%s\n%s\n%s\n%s\n",     apoint->AreaData.Name,
  845.                                            apoint->AreaData.Info,
  846.                                            apoint->AreaData.MBName,
  847.                                            apoint->AreaData.FilePath);
  848.       fprintf(file,"%d\n%d\n%d\n%d\n%d\n", apoint->AreaData.ID,
  849.                                            apoint->AreaData.Type,
  850.                                            apoint->AreaData.ReadLevel,
  851.                                            apoint->AreaData.WriteLevel,
  852.                                            apoint->AreaData.EditLevel);
  853.       fprintf(file,"%ld\n%d\n",            apoint->AreaData.AccessBits,
  854.                                            apoint->AreaData.WriteFlag);
  855.       fprintf(file,"%d\n%d\n%d\n%d\n%d\n", apoint->AreaData.QuoteStr,
  856.                                            apoint->AreaData.PQuoteStr,
  857.                                            apoint->AreaData.ResendStr,
  858.                                            apoint->AreaData.ForwardStr,
  859.                                            apoint->AreaData.OriginStr);
  860.       fprintf(file,"%d\n",                 apoint->AreaData.HoldNum);
  861.       fprintf(file,"%d\n",                 apoint->AreaData.HoldDays);
  862.       fprintf(file,"%d\n%d\n%d\n",         apoint->AreaData.Mother,
  863.                                            apoint->AreaData.Daughter,
  864.                                            apoint->AreaData.Next);
  865.  
  866.       apoint = apoint->Node.mln_Succ;
  867.       }
  868.  
  869.    fclose(file);
  870.  
  871.    ReleaseSemaphore(&KMSBase->AreaSem);
  872.    return TRUE;
  873.    }
  874.  
  875. ///
  876.  
  877. /*********************************
  878.  * Access Control List einlesen  *
  879.  * (Nur bei Programmstart)       *
  880.  *********************************
  881.  * I: ---                        *
  882.  * O: Erfolg? TRUE/FALSE         *
  883.  *********************************/
  884.  
  885. /// "ReadAccessList"
  886.  
  887. BOOL ReadAccessList(VOID)
  888.    {
  889.    struct ACLNode *acl;
  890.    TEXT buffer[LEN_DOSPATH+1];
  891.    TEXT buff[LEN_ACLLINE+1];
  892.    FILE *file;
  893.    UWORD access = 0;
  894.    UBYTE n;
  895.  
  896.    ObtainSemaphore(&KMSBase->SaveSem);
  897.  
  898.    for(n = 0; n < 26; n++)
  899.       KMSBase->ACLIndex[n] = NULL;
  900.    n = 0;
  901.  
  902.    strcpy(buffer, KMSBase->DatDir);
  903.    strcat(buffer, "KMS_ACL.DAT");
  904.  
  905.    if (!(file = fopen(buffer, "r")))
  906.       {
  907.       ReleaseSemaphore(&KMSBase->SaveSem);
  908.       return TRUE;
  909.       }
  910.    else
  911.       {
  912.       while(fgets(buff, LEN_ACLLINE+1, file))
  913.          {
  914.          if (strlen(buff))
  915.             buff[strlen(buff)-1] = '\0'; /* Linefeed am Ende entfernen */
  916.  
  917.          if (!(acl = (struct ACLNode *)AllocMem((ULONG)sizeof(struct ACLNode),MEMF_PUBLIC|MEMF_CLEAR)))
  918.             {
  919.             Out("FATAL ERROR: couldn't AllocMem(ACLNode)");
  920.             fclose(file);
  921.             ReleaseSemaphore(&KMSBase->SaveSem);
  922.             return FALSE;
  923.             }
  924.  
  925.          sscanf(buff, "%31s %hd %hd", acl->UserName, &(acl->AreaID), &access);
  926.          acl->Access = access;
  927.  
  928.          AddTail((struct List *)&KMSBase->AccessList, (struct Node *)acl);
  929.  
  930.          n = toupper(acl->UserName[0]) - 'A';
  931.          if (n > 25)
  932.             n = 25;
  933.  
  934.          if (!KMSBase->ACLIndex[n])
  935.             KMSBase->ACLIndex[n] = acl;
  936.          }
  937.  
  938.       fclose(file);
  939.       }
  940.  
  941.    ReleaseSemaphore(&KMSBase->SaveSem);
  942.  
  943.    return TRUE;
  944.    }
  945.  
  946. ///
  947.  
  948. /*********************************
  949.  * Access Control List sichern   *
  950.  *********************************
  951.  * I: ---                        *
  952.  * O: Erfolg? TRUE/FALSE         *
  953.  *********************************/
  954.  
  955. /// "WriteAccessList"
  956.  
  957. BOOL WriteAccessList(VOID)
  958.    {
  959.    struct ACLNode *acl;
  960.    TEXT buffer[LEN_DOSPATH+1];
  961.    FILE *file;
  962.  
  963.    ObtainSemaphore(&KMSBase->SaveSem);
  964.  
  965.    strcpy(buffer, KMSBase->DatDir);
  966.    strcat(buffer, "KMS_ACL.DAT");
  967.  
  968.    file = fopen(buffer, "w");
  969.    if (!file)
  970.       {
  971.       Out("FATAL ERROR: couldn't write KMS_ACL.DAT");
  972.       ReleaseSemaphore(&KMSBase->SaveSem);
  973.       return FALSE;
  974.       }
  975.  
  976.    acl = (struct ACLNode *)KMSBase->AccessList.mlh_Head;
  977.    while(acl->Node.mln_Succ)
  978.       {
  979.       fprintf(file, "%s %d %d\n", acl->UserName, acl->AreaID, acl->Access);
  980.       acl = acl->Node.mln_Succ;
  981.       }
  982.  
  983.    fclose(file);
  984.  
  985.    ReleaseSemaphore(&KMSBase->SaveSem);
  986.    
  987.    return TRUE;
  988.    }
  989.  
  990. ///
  991.  
  992. /******************************************
  993.  * System/Userdaten sichern               *
  994.  ******************************************
  995.  * I: ---                                 *
  996.  * O: ---                                 *
  997.  ******************************************/
  998.  
  999. /// "SaveData"
  1000.  
  1001. VOID SaveData(VOID)
  1002.    {
  1003.    if (KMSBase->Modified & MODIFIED_AREAS)
  1004.       WriteAreaList();
  1005.  
  1006.    if (KMSBase->Modified & MODIFIED_ACL)
  1007.       WriteAccessList();
  1008.  
  1009.    WriteUserList();
  1010.  
  1011.    WriteSysDat();
  1012.  
  1013.    KMSBase->Modified = 0;
  1014.    }
  1015.  
  1016. ///
  1017.  
  1018. /****************************
  1019.  * System.dat einlesen      *
  1020.  ****************************
  1021.  * I: ---                   *
  1022.  * O: ---                   *
  1023.  ****************************/
  1024.  
  1025. /// "ReadSysDat"
  1026.  
  1027. VOID ReadSysDat(VOID)
  1028.    {
  1029.    TEXT dos[LEN_DOSPATH+1];
  1030.    TEXT buff[LEN_NUMBER+LEN_ACCBITNAME+2];
  1031.    UWORD n;
  1032.    FILE *datei;
  1033.  
  1034.    ObtainSemaphore(&KMSBase->SaveSem);
  1035.  
  1036.    strcpy(dos, KMSBase->DatDir);
  1037.    strcat(dos, "KMS_SYSTEM.DAT");
  1038.  
  1039.    if (datei = fopen(dos, "r"))
  1040.       {
  1041.       fgets(buff, LEN_NUMBER+2, datei);
  1042.       KMSBase->SystemStartups = atol(buff) + 1;
  1043.  
  1044.       for(n = 0; n < 32; n++)
  1045.          {
  1046.          *buff = '\0';
  1047.          if (fgets(buff, LEN_ACCBITNAME+2, datei))
  1048.             buff[strlen(buff)-1] = '\0';
  1049.  
  1050.          if (!strlen(buff))
  1051.             sprintf(KMSBase->AccBitNames[n], "[Bit#%02d]", n+1);
  1052.          else
  1053.             strcpy(KMSBase->AccBitNames[n], buff);
  1054.          }
  1055.  
  1056.       fclose(datei);
  1057.       }
  1058.    else
  1059.       {
  1060.       KMSBase->SystemStartups = 1;
  1061.  
  1062.       for(n = 0; n < 32; n++)
  1063.          sprintf(KMSBase->AccBitNames[n], "[Bit#%02d]", n+1);
  1064.       }
  1065.  
  1066.    ReleaseSemaphore(&KMSBase->SaveSem);
  1067.    }
  1068.  
  1069. ///
  1070.  
  1071. /***************************
  1072.  * Systemdaten speichern   *
  1073.  ***************************
  1074.  * I: ---                  *
  1075.  * O: ---                  *
  1076.  ***************************/
  1077.  
  1078. /// "WriteSysDat"
  1079.  
  1080. VOID WriteSysDat(VOID)
  1081.    {
  1082.    FILE *datei;
  1083.    TEXT dos[LEN_DOSPATH+1];
  1084.    UBYTE n;
  1085.  
  1086.    ObtainSemaphore(&KMSBase->SaveSem);
  1087.  
  1088.    strcpy(dos, KMSBase->DatDir);
  1089.    strcat(dos, "KMS_SYSTEM.DAT");
  1090.  
  1091.    datei = fopen(dos, "w");
  1092.    if (datei)
  1093.       {
  1094.       fprintf(datei, "%ld\n", KMSBase->SystemStartups);
  1095.       for(n = 0; n < 32; n++)
  1096.          fprintf(datei, "%s\n", KMSBase->AccBitNames[n]);
  1097.  
  1098.       fclose(datei);
  1099.       }
  1100.    else
  1101.       Out("FATAL ERROR: couldn't write KMS_SYSTEM.DAT");
  1102.  
  1103.    ReleaseSemaphore(&KMSBase->SaveSem);
  1104.    }
  1105.  
  1106. ///
  1107.  
  1108. /************************************
  1109.  * Master wartet auf Einsamkeit ;-) *
  1110.  ************************************
  1111.  * I: ---                           *
  1112.  * O: Erfolg Ja/Nein                *
  1113.  ************************************/
  1114.  
  1115. /// "WaitUntilAlone"
  1116.  
  1117. BOOL WaitUntilAlone(VOID)
  1118.    {
  1119.    /* Warten, bis kein Slave mehr anwesend */
  1120.  
  1121.    /* Solange noch ein Eintrag in Memberliste... */
  1122.  
  1123.    while(KMSBase->MemberList.mlh_Head->mln_Succ)
  1124.       {
  1125.       Delay(50);
  1126.       dispRexxPort();
  1127.       }
  1128.  
  1129.    return TRUE;
  1130.    }
  1131.  
  1132. ///
  1133.  
  1134. /******************
  1135.  * Sendeschluß... *
  1136.  ******************
  1137.  *** I: Exit-Code *
  1138.  *** O: ---       *
  1139.  ******************/
  1140.  
  1141. /// "Sense"
  1142.  
  1143. VOID Sense(UBYTE exitcode)
  1144.    {
  1145.    /* Rexx-Port killen */
  1146.  
  1147.    dnRexxPort();
  1148.  
  1149.    /* Speicher-Freigaben */
  1150.  
  1151.    if (KMSBase)
  1152.       {
  1153.       if (KMSBase->SysMsgs)
  1154.          FreeVec(KMSBase->SysMsgs);
  1155.  
  1156.       /* Befehlsliste freigeben */
  1157.  
  1158.       struct CommandNode *cpoint = KMSBase->CommandList.mlh_Head;
  1159.       while(cpoint->Node.mln_Succ)
  1160.          {
  1161.          struct CommandNode *nextcpoint = cpoint->Node.mln_Succ;
  1162.          Remove((struct Node *)cpoint);
  1163.          FreeMem(cpoint, (ULONG)sizeof(struct CommandNode));
  1164.          cpoint = nextcpoint;
  1165.          }
  1166.  
  1167.       /* Access Control List freigeben */
  1168.  
  1169.       struct ACLNode *acl = KMSBase->AccessList.mlh_Head;
  1170.       while(acl->Node.mln_Succ)
  1171.          {
  1172.          struct ACLNode *nextacl = acl->Node.mln_Succ;
  1173.          Remove((struct Node *)acl);
  1174.          FreeMem(acl, (ULONG)sizeof(struct ACLNode));
  1175.          acl = nextacl;
  1176.          }
  1177.  
  1178.       /* Weitere Freigaben */
  1179.  
  1180.       if (KMSBase->BinDir)
  1181.          free(KMSBase->BinDir);
  1182.       if (KMSBase->TxtDir)
  1183.          free(KMSBase->TxtDir);
  1184.       if (KMSBase->RexxDir)
  1185.          free(KMSBase->RexxDir);
  1186.       if (KMSBase->LogDir)
  1187.          free(KMSBase->LogDir);
  1188.       if (KMSBase->DoorDir)
  1189.          free(KMSBase->DoorDir);
  1190.       if (KMSBase->TempDir)
  1191.          free(KMSBase->TempDir);
  1192.       if (KMSBase->ModemResetString)
  1193.          free(KMSBase->ModemResetString);
  1194.       if (KMSBase->ModemHangupString)
  1195.          free(KMSBase->ModemHangupString);
  1196.       if (KMSBase->ModemRingString)
  1197.          free(KMSBase->ModemRingString);
  1198.       if (KMSBase->ModemConnectString)
  1199.          free(KMSBase->ModemConnectString);
  1200.       if (KMSBase->ModemSpeedString)
  1201.          free(KMSBase->ModemSpeedString);
  1202.       if (KMSBase->AnswerPhoneString)
  1203.          free(KMSBase->AnswerPhoneString);
  1204.       if (KMSBase->MsgListLine);
  1205.          free(KMSBase->MsgListLine);
  1206.       if (KMSBase->FileListLine);
  1207.          free(KMSBase->FileListLine);
  1208.       if (KMSBase->AreaListPath);
  1209.          free(KMSBase->AreaListPath);
  1210.       if (KMSBase->AreaListInfo);
  1211.          free(KMSBase->AreaListInfo);
  1212.  
  1213.       UBYTE n;
  1214.       for(n = 0; n < 4; n++)
  1215.          if (KMSBase->MsgHead[n])
  1216.             free(KMSBase->MsgHead[n]);
  1217.       for(n = 0; n < 15; n++)
  1218.          if (KMSBase->MsgInfos[n])
  1219.             free(KMSBase->MsgInfos[n]);
  1220.  
  1221.       /* Von der Basis abmelden */
  1222.  
  1223.       ReleaseSemaphore(&KMSBase->BaseSem);
  1224.  
  1225.       /* KMSBase gegebenenfalls wieder entfernen */
  1226.  
  1227.       Forbid();
  1228.       if (KMSBase = (struct KMSBase *)FindSemaphore(KMSBASENAME))
  1229.          {
  1230.          if (AttemptSemaphore(&KMSBase->BaseSem))
  1231.             {
  1232.             Permit();
  1233.  
  1234.             /* Arealiste freigeben */
  1235.  
  1236.             struct AreaNode *apoint = KMSBase->AreaList.mlh_Head;
  1237.             while(apoint->Node.mln_Succ)
  1238.                {
  1239.                struct AreaNode *nextapoint = apoint->Node.mln_Succ;
  1240.                Remove((struct Node *)apoint);
  1241.                FreeMem(apoint, (ULONG)sizeof(struct AreaNode));
  1242.                apoint = nextapoint;
  1243.                }
  1244.  
  1245.             /* Userliste freigeben */
  1246.  
  1247.             struct UserNode *upoint = KMSBase->UserList.mlh_Head;
  1248.             while(upoint->Node.mln_Succ)
  1249.                {
  1250.                struct UserNode *nextupoint = upoint->Node.mln_Succ;
  1251.                Remove((struct Node *)upoint);
  1252.                FreeMem(upoint, (ULONG)sizeof(struct UserNode));
  1253.                upoint = nextupoint;
  1254.                }
  1255.  
  1256.             if (KMSBase->DatDir)
  1257.                FreeMem(KMSBase->DatDir, strlen(KMSBase->DatDir) + 1);
  1258.             if (KMSBase->UserDir)
  1259.                FreeMem(KMSBase->UserDir, strlen(KMSBase->UserDir) + 1);
  1260.  
  1261.             RemSemaphore(&KMSBase->BaseSem);
  1262.  
  1263.             ObtainSemaphore(&KMSBase->UserSem);
  1264.             ReleaseSemaphore(&KMSBase->UserSem);
  1265.             ObtainSemaphore(&KMSBase->AreaSem);
  1266.             ReleaseSemaphore(&KMSBase->AreaSem);
  1267.             ObtainSemaphore(&KMSBase->SaveSem);
  1268.             ReleaseSemaphore(&KMSBase->SaveSem);
  1269.  
  1270.             ReleaseSemaphore(&KMSBase->BaseSem);
  1271.  
  1272.             FreeMem(KMSBase->BaseSem.ss_Link.ln_Name, sizeof(KMSBASENAME)+1);
  1273.  
  1274.             FreeMem(KMSBase, sizeof(struct KMSBase));
  1275.             }
  1276.          else
  1277.             Permit();
  1278.          }
  1279.       else
  1280.          Permit();
  1281.       }
  1282.  
  1283.    if (SysUMSAccount)
  1284.       UMSLogout(SysUMSAccount);
  1285.  
  1286.    if (ShutDown == SHUTDOWN_IMMED_SYS)
  1287.       UMSServerControl(NULL, UMSSC_Quit);
  1288.  
  1289.    if (StdOut)
  1290.       Close(StdOut);
  1291.  
  1292.    struct MsgPort *serverport;
  1293.    Forbid();
  1294.    if (serverport = FindPort(ServerPort))
  1295.       {
  1296.       struct Message *smsg;
  1297.  
  1298.       RemPort(serverport);
  1299.       while(smsg = GetMsg(serverport))
  1300.          ReplyMsg(smsg);
  1301.       DeletePort(serverport);
  1302.       }
  1303.    Permit();
  1304.  
  1305.    exit(exitcode);
  1306.    }
  1307.  
  1308. ///
  1309.  
  1310. /*******************
  1311.  * Standardausgabe *
  1312.  *******************
  1313.  *** I: Text       *
  1314.  *** O: ---        *
  1315.  *******************/
  1316.  
  1317. /// "Out"
  1318.  
  1319. VOID Out(STRPTR str)
  1320.    {
  1321.    if (StdOut && str)
  1322.       {
  1323.       Write(StdOut, str, (LONG)strlen(str));
  1324.       Write(StdOut, "\n", 1);
  1325.       }
  1326.    }
  1327.  
  1328. ///
  1329.  
  1330. /*******************************************
  1331.  * Zeile aus SysMsgList lesen              *
  1332.  *******************************************
  1333.  * I: ZielBuffer, Max. Länge               *
  1334.  * O: Neue Position in SysMsg-Datei        *
  1335.  *******************************************/
  1336.  
  1337. /// "GetSysMsgLine"
  1338.  
  1339. STRPTR GetSysMsgLine(STRPTR sysmsgdat, STRPTR buff, UWORD maxlen)
  1340.    {
  1341.    STRPTR buffalt = buff;
  1342.    TEXT c = *(sysmsgdat++);
  1343.  
  1344.    /* Zeile einlesen */
  1345.  
  1346.    maxlen++;
  1347.    while(c != '\n' && c > 0 && --maxlen)
  1348.       {
  1349.       *(buff++) = c;
  1350.       c = *(sysmsgdat++);
  1351.       }
  1352.    *buff = '\0';
  1353.  
  1354.    /* Falls Zeile zu lang, Rest der Zeile ueberlesen */
  1355.  
  1356.    if (c != '\n')
  1357.       while(c != '\n' && c > 0)
  1358.          c = *(sysmsgdat++);
  1359.  
  1360.    if (c == '\n')
  1361.       return sysmsgdat;
  1362.    else
  1363.       return NULL;
  1364.    }
  1365.  
  1366. ///
  1367.  
  1368. /*********************************
  1369.  * Areadatei initialisieren      *
  1370.  *********************************
  1371.  * I: ---                        *
  1372.  * O: Erfolg TRUE/FALSE          *
  1373.  *********************************/
  1374.  
  1375. /// "InitAreaFile"
  1376.  
  1377. BOOL InitAreaFile(VOID)
  1378.    {
  1379.    TEXT buffer[LEN_DOSPATH+1];
  1380.    struct Area area;
  1381.    FILE *file;
  1382.  
  1383.    ObtainSemaphore(&KMSBase->AreaSem);
  1384.  
  1385.    strcpy(buffer, KMSBase->DatDir);
  1386.    strcat(buffer, "KMS_AREAS.DAT");
  1387.  
  1388.    if (!(file = fopen(buffer, "w")))
  1389.       {
  1390.       Out("FATAL ERROR: couldn't create KMS_AREAS.DAT");
  1391.       ReleaseSemaphore(&KMSBase->AreaSem);
  1392.       return FALSE;
  1393.       }
  1394.  
  1395.    clrmem(&area, sizeof(struct Area));
  1396.  
  1397.    strcpy(area.Name, "PRIVAT");
  1398.    strcpy(area.Info, "- Private Mail -");
  1399.    strcpy(area.MBName, "");
  1400.    strcpy(area.FilePath, "KMS:Files/");
  1401.    area.ID = 1;
  1402.    area.Type = ATYPE_PRIVATE;
  1403.    area.ReadLevel = 1;
  1404.    area.WriteLevel = 1;
  1405.    area.EditLevel = 255;
  1406.    area.QuoteStr = 1;
  1407.    area.PQuoteStr = 1;
  1408.    area.ResendStr = 1;
  1409.    area.ForwardStr = 1;
  1410.    area.OriginStr = 1;
  1411.    area.HoldNum = 0;
  1412.    area.HoldDays = 0;
  1413.    fprintf(file, "%s\n%s\n%s\n%s\n",     area.Name,
  1414.                                          area.Info,
  1415.                                          area.MBName,
  1416.                                          area.FilePath);
  1417.    fprintf(file, "%d\n%d\n%d\n%d\n%d\n", area.ID,
  1418.                                          area.Type,
  1419.                                          area.ReadLevel,
  1420.                                          area.WriteLevel,
  1421.                                          area.EditLevel);
  1422.    fprintf(file, "%ld\n%d\n",            area.AccessBits,
  1423.                                          area.WriteFlag);
  1424.    fprintf(file, "%d\n%d\n%d\n%d\n%d\n", area.QuoteStr,
  1425.                                          area.PQuoteStr,
  1426.                                          area.ResendStr,
  1427.                                          area.ForwardStr,
  1428.                                          area.OriginStr);
  1429.    fprintf(file, "%d\n",                 area.HoldNum);
  1430.    fprintf(file, "%d\n",                 area.HoldDays);
  1431.    fprintf(file, "%d\n%d\n%d\n",         area.Mother,
  1432.                                          area.Daughter,
  1433.                                          area.Next);
  1434.  
  1435.    fclose(file);
  1436.  
  1437.    ReleaseSemaphore(&KMSBase->AreaSem);
  1438.  
  1439.    return TRUE;
  1440.    }
  1441.  
  1442. ///
  1443.  
  1444. /*********************************
  1445.  * Neue Userdatei anlegen        *
  1446.  *********************************
  1447.  * I: ---                        *
  1448.  * O: Erfolg TRUE/FALSE          *
  1449.  *********************************/
  1450.  
  1451. /// "InitUAF"
  1452.  
  1453. BOOL InitUAF(VOID)
  1454.    {
  1455.    FILE *file;
  1456.    struct Userdaten user;
  1457.    TEXT buffer[LEN_DOSPATH+1];
  1458.    TEXT buff[LEN_DOSPATH*2+LEN_USERNAME+21+1];
  1459.    BPTR lock;
  1460.  
  1461.    ObtainSemaphore(&KMSBase->UserSem);
  1462.  
  1463.    strcpy(buffer, KMSBase->DatDir);
  1464.    strcat(buffer, "KMS_UAF.DAT");
  1465.  
  1466.    if (!(file = fopen(buffer, "w")))
  1467.       {
  1468.       Out("FATAL ERROR: couldn't create KMS_UAF.DAT");
  1469.       ReleaseSemaphore(&KMSBase->UserSem);
  1470.       return FALSE;
  1471.       }
  1472.  
  1473.    /* KMS-System-Account */
  1474.  
  1475.    clrmem(&user, sizeof(struct Userdaten));
  1476.  
  1477.    user.ID = 1;
  1478.    user.CharSet = 0;
  1479.    user.Flags = UF_EMU_ANSI|UF_EDIT_INSERT|UF_AUTO_LIST|UF_AUTO_AREALIST|UF_RMODE_NEW|UF_SCREEN_ED;
  1480.    strcpy(user.Name, "System");
  1481.    strcpy(user.RealName, "KMS System");
  1482.    strcpy(user.City, "Ankh-Morpork");
  1483.    user.Level = 255;
  1484.    user.LineLen = 80;
  1485.    user.PageLen = 25;
  1486.    user.Quota = 10;
  1487.    strcpy(user.Prompt, "System> ");
  1488.  
  1489.    fprintf(file, "%d\n%s\n%s\n%s\n",     user.ID,
  1490.                                          user.Name,
  1491.                                          user.RealName,
  1492.                                          user.Street);
  1493.    fprintf(file, "%s\n%s\n%s\n",         user.City,
  1494.                                          user.Phone,
  1495.                                          user.Prompt);
  1496.    fprintf(file, "%d\n%d\n%ld\n",        user.Level,
  1497.                                          user.Calls,
  1498.                                          user.LastCall);
  1499.    fprintf(file, "%d\n%d\n%d\n%d\n",     user.CharSet,
  1500.                                          user.PageLen,
  1501.                                          user.LineLen,
  1502.                                          user.Protocol);
  1503.    fprintf(file, "%ld\n%ld\n%d\n\n",     user.Flags,
  1504.                                          user.AccessBits,
  1505.                                          user.Quota);
  1506.  
  1507.    /* Neues Paßwort in ums.config festhalten */
  1508.  
  1509.    WriteUMSConfigTags(SysUMSAccount, UMSTAG_CfgUser, user.RealName,
  1510.                                      UMSTAG_CfgName, "PASSWORD",
  1511.                                      UMSTAG_CfgData, "",
  1512.                                      TAG_DONE);
  1513.  
  1514.    /* User-Directory anlegen */
  1515.  
  1516.    strcpy(buffer, KMSBase->UserDir);
  1517.    strcat(buffer, user.Name);
  1518.  
  1519.    if (lock = CreateDir(buffer))
  1520.       {
  1521.       UnLock(lock);
  1522.  
  1523.       /* LOGIN.COM kopieren */
  1524.  
  1525.       sprintf(buff, "Copy >NIL: %sLOGIN.COM %s", KMSBase->UserDir, buffer);
  1526.       system(buff);
  1527.       }
  1528.  
  1529.    /* KMS-Default-Account */
  1530.  
  1531.    clrmem(&user, sizeof(struct Userdaten));
  1532.  
  1533.    user.ID = 2;
  1534.    user.CharSet = 0;
  1535.    user.Flags = UF_EMU_ANSI|UF_EDIT_INSERT|UF_AUTO_LIST|UF_AUTO_AREALIST|UF_RMODE_NEW|UF_SCREEN_ED;
  1536.    strcpy(user.Name, "Default");
  1537.    strcpy(user.RealName, "KMS Default");
  1538.    strcpy(user.City, "Pern");
  1539.    user.Level = 10;
  1540.    user.LineLen = 80;
  1541.    user.PageLen = 25;
  1542.    user.Quota = 10;
  1543.    strcpy(user.Prompt, "[%p]> ");
  1544.  
  1545.    fprintf(file, "%d\n%s\n%s\n%s\n",     user.ID,
  1546.                                          user.Name,
  1547.                                          user.RealName,
  1548.                                          user.Street);
  1549.    fprintf(file, "%s\n%s\n%s\n",         user.City,
  1550.                                          user.Phone,
  1551.                                          user.Prompt);
  1552.    fprintf(file, "%d\n%d\n%ld\n",        user.Level,
  1553.                                          user.Calls,
  1554.                                          user.LastCall);
  1555.    fprintf(file, "%d\n%d\n%d\n%d\n",     user.CharSet,
  1556.                                          user.PageLen,
  1557.                                          user.LineLen,
  1558.                                          user.Protocol);
  1559.    fprintf(file, "%ld\n%ld\n%d\n\n",     user.Flags,
  1560.                                          user.AccessBits,
  1561.                                          user.Quota);
  1562.  
  1563.    /* Neues Paßwort in ums.config festhalten */
  1564.  
  1565.    WriteUMSConfigTags(SysUMSAccount, UMSTAG_CfgUser, user.RealName,
  1566.                                      UMSTAG_CfgName, "PASSWORD",
  1567.                                      UMSTAG_CfgData, "",
  1568.                                      TAG_DONE);
  1569.  
  1570.    /* User-Directory anlegen */
  1571.  
  1572.    strcpy(buffer, KMSBase->UserDir);
  1573.    strcat(buffer, user.Name);
  1574.  
  1575.    if (lock = CreateDir(buffer))
  1576.       {
  1577.       UnLock(lock);
  1578.  
  1579.       /* LOGIN.COM kopieren */
  1580.  
  1581.       sprintf(buff, "Copy >NIL: %sLOGIN.COM %s", KMSBase->UserDir, buffer);
  1582.       system(buff);
  1583.       }
  1584.  
  1585.    /* GAST-Account */
  1586.  
  1587.    clrmem(&user, sizeof(struct Userdaten));
  1588.  
  1589.    user.ID = 3;
  1590.    user.CharSet = 0;
  1591.    user.Flags = UF_EMU_ANSI|UF_EDIT_INSERT|UF_AUTO_LIST|UF_AUTO_AREALIST|UF_RMODE_NEW|UF_SCREEN_ED;
  1592.    strcpy(user.Name, "Gast");
  1593.    strcpy(user.RealName, "KMS Gast");
  1594.    strcpy(user.City, "Ankh-Morpork");
  1595.    user.Level = 1;
  1596.    user.LineLen = 80;
  1597.    user.PageLen = 25;
  1598.    user.Quota = 0;
  1599.    strcpy(user.Prompt, "[%p]> ");
  1600.  
  1601.    fprintf(file, "%d\n%s\n%s\n%s\n",     user.ID,
  1602.                                          user.Name,
  1603.                                          user.RealName,
  1604.                                          user.Street);
  1605.    fprintf(file, "%s\n%s\n%s\n",         user.City,
  1606.                                          user.Phone,
  1607.                                          user.Prompt);
  1608.    fprintf(file, "%d\n%d\n%ld\n",        user.Level,
  1609.                                          user.Calls,
  1610.                                          user.LastCall);
  1611.    fprintf(file, "%d\n%d\n%d\n%d\n",     user.CharSet,
  1612.                                          user.PageLen,
  1613.                                          user.LineLen,
  1614.                                          user.Protocol);
  1615.    fprintf(file, "%ld\n%ld\n%d\n\n",     user.Flags,
  1616.                                          user.AccessBits,
  1617.                                          user.Quota);
  1618.  
  1619.    /* Neues Paßwort in ums.config festhalten */
  1620.  
  1621.    WriteUMSConfigTags(SysUMSAccount, UMSTAG_CfgUser, user.RealName,
  1622.                                      UMSTAG_CfgName, "PASSWORD",
  1623.                                      UMSTAG_CfgData, "",
  1624.                                      TAG_DONE);
  1625.  
  1626.    /* User-Directory anlegen */
  1627.  
  1628.    strcpy(buffer, KMSBase->UserDir);
  1629.    strcat(buffer, user.Name);
  1630.  
  1631.    if (lock = CreateDir(buffer))
  1632.       UnLock(lock);
  1633.  
  1634.    fclose(file);
  1635.  
  1636.    ReleaseSemaphore(&KMSBase->UserSem);
  1637.  
  1638.    return TRUE;
  1639.    }
  1640.  
  1641. ///
  1642.  
  1643. /********************************
  1644.  * KMSBase besorgen             *
  1645.  ********************************
  1646.  * I: ---                       *
  1647.  * O: struct KMSBase *          *
  1648.  ********************************/
  1649.  
  1650. /// "GetKMSBase"
  1651.  
  1652. struct KMSBase *GetKMSBase(VOID)
  1653.    {
  1654.    STRPTR bname;
  1655.  
  1656.    /* KMSBase erzeugen, falls nicht vorhanden */
  1657.  
  1658.    Forbid();
  1659.  
  1660.    if (!(KMSBase = (struct KMSBase *)FindSemaphore(KMSBASENAME)))
  1661.       {
  1662.       bname = AllocMem((ULONG)sizeof(KMSBASENAME)+1, MEMF_PUBLIC|MEMF_CLEAR);
  1663.       if (bname)
  1664.          {
  1665.          strcpy(bname, KMSBASENAME);
  1666.  
  1667.          if (KMSBase = AllocMem((ULONG)sizeof(struct KMSBase), MEMF_PUBLIC|MEMF_CLEAR))
  1668.             {
  1669.             KMSBase->BaseSem.ss_Link.ln_Pri = 0;
  1670.             KMSBase->BaseSem.ss_Link.ln_Name = bname;
  1671.             KMSBase->UserSem.ss_Link.ln_Pri = 0;
  1672.             KMSBase->UserSem.ss_Link.ln_Name = NULL;
  1673.             KMSBase->AreaSem.ss_Link.ln_Pri = 0;
  1674.             KMSBase->AreaSem.ss_Link.ln_Name = NULL;
  1675.             KMSBase->SaveSem.ss_Link.ln_Pri = 0;
  1676.             KMSBase->SaveSem.ss_Link.ln_Name = NULL;
  1677.  
  1678.             NewList((struct List *)&KMSBase->AreaList);
  1679.             NewList((struct List *)&KMSBase->UserList);
  1680.  
  1681.             AddSemaphore(&KMSBase->BaseSem);
  1682.             InitSemaphore(&KMSBase->UserSem);
  1683.             InitSemaphore(&KMSBase->AreaSem);
  1684.             InitSemaphore(&KMSBase->SaveSem);
  1685.  
  1686.             ObtainSemaphore(&KMSBase->BaseSem);
  1687.  
  1688.             Permit();
  1689.  
  1690.             TEXT varbuff[32] = "";
  1691.             TEXT pwbuff[32] = "";
  1692.             GetVar("KMSMB", varbuff, sizeof(varbuff), NULL);
  1693.             GetVar("KMSPWD", pwbuff, sizeof(pwbuff), NULL);
  1694.             if (!(SysUMSAccount = UMSRLogin(varbuff, "KMS", pwbuff)))
  1695.                {
  1696.                ReleaseSemaphore(&KMSBase->BaseSem);
  1697.                Out("FATAL ERROR: couldn't log into UMS");
  1698.                return NULL;
  1699.                }
  1700.  
  1701.             STRPTR string;
  1702.  
  1703.             if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.datdir", TAG_DONE))
  1704.                {
  1705.                KMSBase->DatDir = AllocMem((ULONG)(strlen(string)+1), MEMF_PUBLIC|MEMF_CLEAR);
  1706.                if (KMSBase->DatDir)
  1707.                   strcpy(KMSBase->DatDir, string);
  1708.  
  1709.                FreeUMSConfig(SysUMSAccount, string);
  1710.  
  1711.                if (!KMSBase->DatDir)
  1712.                   {
  1713.                   Out("FATAL ERROR: out of memory");
  1714.                   return NULL;
  1715.                   }
  1716.                }
  1717.             else
  1718.                {
  1719.                KMSBase->DatDir = AllocMem((ULONG)(strlen("Data/")+1), MEMF_PUBLIC|MEMF_CLEAR);
  1720.                if (KMSBase->DatDir)
  1721.                   strcpy(KMSBase->DatDir, "Data/");
  1722.                else
  1723.                   {
  1724.                   Out("FATAL ERROR: out of memory");
  1725.                   return NULL;
  1726.                   }
  1727.                }
  1728.  
  1729.             if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.userdir", TAG_DONE))
  1730.                {
  1731.                KMSBase->UserDir = AllocMem((ULONG)(strlen(string)+1), MEMF_PUBLIC|MEMF_CLEAR);
  1732.                if (KMSBase->UserDir)
  1733.                   strcpy(KMSBase->UserDir, string);
  1734.  
  1735.                FreeUMSConfig(SysUMSAccount, string);
  1736.  
  1737.                if (!KMSBase->UserDir)
  1738.                   {
  1739.                   Out("FATAL ERROR: out of memory");
  1740.                   return NULL;
  1741.                   }
  1742.                }
  1743.             else
  1744.                {
  1745.                KMSBase->UserDir = AllocMem((ULONG)(strlen("User/")+1), MEMF_PUBLIC|MEMF_CLEAR);
  1746.                if (KMSBase->UserDir)
  1747.                   strcpy(KMSBase->UserDir, "User/");
  1748.                else
  1749.                   {
  1750.                   Out("FATAL ERROR: out of memory");
  1751.                   return NULL;
  1752.                   }
  1753.                }
  1754.  
  1755.             ReleaseSemaphore(&KMSBase->BaseSem);
  1756.             ObtainSemaphoreShared(&KMSBase->BaseSem);
  1757.             }
  1758.          else
  1759.             {
  1760.             Permit();
  1761.  
  1762.             if (bname)
  1763.                FreeMem(bname, sizeof(KMSBASENAME)+1);
  1764.  
  1765.             Out("FATAL ERROR: out of memory");
  1766.  
  1767.             return NULL;
  1768.             }
  1769.          }
  1770.       else
  1771.          {
  1772.          Permit();
  1773.  
  1774.          Out("FATAL ERROR: out of memory");
  1775.  
  1776.          return NULL;
  1777.          }
  1778.       }
  1779.    else
  1780.       {
  1781.       ObtainSemaphoreShared(&KMSBase->BaseSem);
  1782.  
  1783.       Permit();
  1784.       }
  1785.  
  1786.    /* Diverse Initialisierungen */
  1787.  
  1788.    KMSBase->Modified = 0;
  1789.  
  1790.    /* Systemlisten initialisieren */
  1791.  
  1792.    NewList((struct List *)&KMSBase->MemberList);
  1793.    NewList((struct List *)&KMSBase->CommandList);
  1794.    NewList((struct List *)&KMSBase->AccessList);
  1795.  
  1796.    /* Default-Konfiguration einstellen */
  1797.  
  1798.    KMSBase->LoginTries = 3;
  1799.    KMSBase->InputTimeout = 300;
  1800.    KMSBase->InputTimeoutWarnings = 2;
  1801.    KMSBase->MaxConnectTime = 120;
  1802.    KMSBase->MaxConnectWarnings = 3;
  1803.    KMSBase->MaxHistCount = 30;
  1804.    KMSBase->XOFFTimeout = 300;
  1805.  
  1806.    strcpy(KMSBase->AFlags, "FPNRWE");
  1807.    strcpy(KMSBase->YNText, "YN");
  1808.    strcpy(KMSBase->MoreText, "YNC");
  1809.    strcpy(KMSBase->MorePrompt, "More [Y]/N/C?");
  1810.  
  1811.    /* Vorhandene Konfigurations-Token aus ums.config lesen */
  1812.  
  1813.    if (!SysUMSAccount)
  1814.       {
  1815.       TEXT varbuff[32] = "";
  1816.       GetVar("KMSMB", varbuff, sizeof(varbuff), NULL);
  1817.       if (!(SysUMSAccount = UMSRLogin(varbuff, "KMS", "")))
  1818.          {
  1819.          Out("FATAL ERROR: couldn't log into UMS");
  1820.          return NULL;
  1821.          }
  1822.       }
  1823.  
  1824.    STRPTR string;
  1825.  
  1826.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.loglevel", TAG_DONE))
  1827.       {
  1828.       KMSBase->LogLevel = (UBYTE)atoi(string);
  1829.       FreeUMSConfig(SysUMSAccount, string);
  1830.       }
  1831.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.logintries", TAG_DONE))
  1832.       {
  1833.       if (atoi(string))
  1834.          KMSBase->LoginTries = atoi(string);
  1835.       FreeUMSConfig(SysUMSAccount, string);
  1836.       }
  1837.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.inputtimeout", TAG_DONE))
  1838.       {
  1839.       if (atoi(string))
  1840.          KMSBase->InputTimeout = atoi(string);
  1841.       FreeUMSConfig(SysUMSAccount, string);
  1842.       }
  1843.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.inputtimeoutwarnings", TAG_DONE))
  1844.       {
  1845.       KMSBase->InputTimeoutWarnings = atoi(string);
  1846.       FreeUMSConfig(SysUMSAccount, string);
  1847.       }
  1848.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.maxconnecttime", TAG_DONE))
  1849.       {
  1850.       KMSBase->MaxConnectTime = atoi(string);
  1851.       FreeUMSConfig(SysUMSAccount, string);
  1852.       }
  1853.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.maxconnectwarnings", TAG_DONE))
  1854.       {
  1855.       KMSBase->MaxConnectWarnings = atoi(string);
  1856.       FreeUMSConfig(SysUMSAccount, string);
  1857.       }
  1858.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.maxhistcount", TAG_DONE))
  1859.       {
  1860.       KMSBase->MaxHistCount = atoi(string);
  1861.       FreeUMSConfig(SysUMSAccount, string);
  1862.       }
  1863.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.xofftimeout", TAG_DONE))
  1864.       {
  1865.       KMSBase->XOFFTimeout = atoi(string);
  1866.       FreeUMSConfig(SysUMSAccount, string);
  1867.       }
  1868.  
  1869.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.bindir", TAG_DONE))
  1870.       {
  1871.       KMSBase->BinDir = strdup(string);
  1872.       FreeUMSConfig(SysUMSAccount, string);
  1873.       }
  1874.    else
  1875.       KMSBase->BinDir = strdup("Bin/");
  1876.    if (!KMSBase->BinDir)
  1877.       {
  1878.       Out("FATAL ERROR: out of memory");
  1879.       return NULL;
  1880.       }
  1881.  
  1882.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.txtdir", TAG_DONE))
  1883.       {
  1884.       KMSBase->TxtDir = strdup(string);
  1885.       FreeUMSConfig(SysUMSAccount, string);
  1886.       }
  1887.    else
  1888.       KMSBase->TxtDir = strdup("Text/");
  1889.    if (!KMSBase->TxtDir)
  1890.       {
  1891.       Out("FATAL ERROR: out of memory");
  1892.       return NULL;
  1893.       }
  1894.  
  1895.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.rexxdir", TAG_DONE))
  1896.       {
  1897.       KMSBase->RexxDir = strdup(string);
  1898.       FreeUMSConfig(SysUMSAccount, string);
  1899.       }
  1900.    else
  1901.       KMSBase->RexxDir = strdup("Rexx/");
  1902.    if (!KMSBase->RexxDir)
  1903.       {
  1904.       Out("FATAL ERROR: out of memory");
  1905.       return NULL;
  1906.       }
  1907.  
  1908.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.logdir", TAG_DONE))
  1909.       {
  1910.       KMSBase->LogDir = strdup(string);
  1911.       FreeUMSConfig(SysUMSAccount, string);
  1912.       }
  1913.    else
  1914.       KMSBase->LogDir = strdup("Data/");
  1915.    if (!KMSBase->LogDir)
  1916.       {
  1917.       Out("FATAL ERROR: out of memory");
  1918.       return NULL;
  1919.       }
  1920.  
  1921.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.doordir", TAG_DONE))
  1922.       {
  1923.       KMSBase->DoorDir = strdup(string);
  1924.       FreeUMSConfig(SysUMSAccount, string);
  1925.       }
  1926.    else
  1927.       KMSBase->DoorDir = strdup("Doors/");
  1928.    if (!KMSBase->DoorDir)
  1929.       {
  1930.       Out("FATAL ERROR: out of memory");
  1931.       return NULL;
  1932.       }
  1933.  
  1934.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.tempdir", TAG_DONE))
  1935.       {
  1936.       KMSBase->TempDir = strdup(string);
  1937.       FreeUMSConfig(SysUMSAccount, string);
  1938.       }
  1939.    else
  1940.       KMSBase->TempDir = strdup("T:");
  1941.    if (!KMSBase->TempDir)
  1942.       {
  1943.       Out("FATAL ERROR: out of memory");
  1944.       return NULL;
  1945.       }
  1946.  
  1947.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.modemreset", TAG_DONE))
  1948.       {
  1949.       KMSBase->ModemResetString = strdup(string);
  1950.       FreeUMSConfig(SysUMSAccount, string);
  1951.       }
  1952.    else
  1953.       KMSBase->ModemResetString = strdup("ATZ%M");
  1954.    if (!KMSBase->ModemResetString)
  1955.       {
  1956.       Out("FATAL ERROR: out of memory");
  1957.       return NULL;
  1958.       }
  1959.  
  1960.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.modemhangup", TAG_DONE))
  1961.       {
  1962.       KMSBase->ModemHangupString = strdup(string);
  1963.       FreeUMSConfig(SysUMSAccount, string);
  1964.       }
  1965.    else
  1966.       KMSBase->ModemHangupString = strdup("%P%P+++%P%PATH%M");
  1967.    if (!KMSBase->ModemHangupString)
  1968.       {
  1969.       Out("FATAL ERROR: out of memory");
  1970.       return NULL;
  1971.       }
  1972.    
  1973.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.modemring", TAG_DONE))
  1974.       {
  1975.       KMSBase->ModemRingString = strdup(string);
  1976.       FreeUMSConfig(SysUMSAccount, string);
  1977.       }
  1978.    else
  1979.       KMSBase->ModemRingString = strdup("RING");
  1980.    if (!KMSBase->ModemRingString)
  1981.       {
  1982.       Out("FATAL ERROR: out of memory");
  1983.       return NULL;
  1984.       }
  1985.    
  1986.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.modemconnect", TAG_DONE))
  1987.       {
  1988.       KMSBase->ModemConnectString = strdup(string);
  1989.       FreeUMSConfig(SysUMSAccount, string);
  1990.       }
  1991.    else
  1992.       KMSBase->ModemConnectString = strdup("CONNECT");
  1993.    if (!KMSBase->ModemConnectString)
  1994.       {
  1995.       Out("FATAL ERROR: out of memory");
  1996.       return NULL;
  1997.       }
  1998.    
  1999.    if (string = ReadUMSConfigTags(SysUMSAccount, UMSTAG_CfgName, "KMS.modemanswer", TAG_DONE))
  2000.       {
  2001.       KMSBase->AnswerPhoneString = strdup(string);
  2002.       FreeUMSConfig(SysUMSAccount, string);
  2003.       }
  2004.    else
  2005.       KMSBase->AnswerPhoneString = strdup("ATA%M");
  2006.    if (!KMSBase->AnswerPhoneString)
  2007.       {
  2008.       Out("FATAL ERROR: out of memory");
  2009.       return NULL;
  2010.       }
  2011.  
  2012.    /* Div. Text-Daten aus KMS_SYSTEM.TXT lesen */
  2013.  
  2014.    if (!GetData())
  2015.       return NULL;
  2016.  
  2017.    /* Systemdaten einlesen */
  2018.  
  2019.    ReadSysDat();
  2020.  
  2021.    /* Befehlsliste einlesen */
  2022.  
  2023.    TEXT line[82], dos[LEN_DOSPATH+1];
  2024.    struct CommandNode *cpoint;
  2025.    FILE *datei;
  2026.  
  2027.    strcpy(dos, KMSBase->DatDir);
  2028.    strcat(dos, "KMS_COMMANDS.DAT");
  2029.  
  2030.    if (!(datei = fopen(dos, "r")))
  2031.       {
  2032.       Out("FATAL ERROR: couldn't open KMS_COMMANDS.DAT");
  2033.       return NULL;
  2034.       }
  2035.    else
  2036.       {
  2037.       while(fgets(line, 82, datei))
  2038.          {
  2039.          if (!(cpoint = (struct CommandNode *)AllocMem((ULONG)sizeof(struct CommandNode), MEMF_PUBLIC|MEMF_CLEAR)))
  2040.             {
  2041.             Out("FATAL ERROR: couldn't AllocMem(CommandNode)");
  2042.             fclose(datei);
  2043.             return NULL;
  2044.             }
  2045.          sscanf(line, "%15s %30s %hd %hd", cpoint->Name, cpoint->DisplayName, &(cpoint->ID), &(cpoint->Level));
  2046.  
  2047.          AddTail((struct List *)&KMSBase->CommandList, (struct Node *)cpoint);
  2048.          }
  2049.       fclose(datei);
  2050.       }
  2051.  
  2052.    /* Zeichenkonvertiertabellen einlesen */
  2053.  
  2054.    UBYTE n;
  2055.    for(n = 0; n < 10; n++)
  2056.       GetCharTable(n);
  2057.  
  2058.    /* Arealiste einlesen oder anlegen, falls nicht vorhanden */
  2059.  
  2060.    if (!ReadAreaList())
  2061.       {
  2062.       InitAreaFile();
  2063.       if (!ReadAreaList())
  2064.          {
  2065.          Out("FATAL ERROR: couldn't create or read KMS_AREAS.DAT");
  2066.          return NULL;
  2067.          }
  2068.       }
  2069.  
  2070.    /* Userliste einlesen oder anlegen, falls nicht vorhanden */
  2071.  
  2072.    if (!ReadUserList())
  2073.       {
  2074.       InitUAF();
  2075.       if (!ReadUserList())
  2076.          {
  2077.          Out("FATAL ERROR: couldn't create or read KMS_UAF.DAT");
  2078.          return NULL;
  2079.          }
  2080.       }
  2081.  
  2082.    /* Access Control List einlesen */
  2083.  
  2084.    if (!ReadAccessList())
  2085.       return NULL;
  2086.  
  2087.    return KMSBase;
  2088.    }
  2089.  
  2090. ///
  2091.  
  2092.